import logging


class DatabaseLogHandler(logging.Handler):
    """
    统一的数据库日志处理器：
    - 无 request：仅写 level/message
    - 有 request：尽可能补充 method/path/status_code/duration/ip/user_agent/username
    - 失败不影响主流程（handleError）
    """

    def emit(self, record):
        from user.models import SystemLog  # 避免循环导入

        try:
            # 基础日志信息
            payload = {
                "level": getattr(
                    record, "levelname", "INFO"
                ),  # 去 record 里拿 levelname，没有就默认 INFO”
                "message": self._safe_message(
                    record
                ),  # “调用我自己定义的一个方法 _safe_message，帮我提取消息文本”
            }
            # 尝试从 record 中提取 request 相关信息
            req = getattr(record, "request", None)
            if req is not None:
                payload["method"] = getattr(req, "method", None)
                payload["path"] = getattr(req, "path", None)
                # 这两个通常通过 extra 注入
                payload["status_code"] = getattr(record, "status_code", None)
                payload["duration"] = getattr(record, "duration", None)

                # IP 地址
                meta = getattr(req, "META", {}) or {}  # 防止 META 为 None
                xff = meta.get("HTTP_X_FORWARDED_FOR")  # 从请求头中尝试取出真实 IP
                if xff:
                    payload["ip_address"] = xff.split(",")[0].strip()
                else:
                    payload["ip_address"] = meta.get("REMOTE_ADDR")

                # 用户代理
                payload["user_agent"] = meta.get("HTTP_USER_AGENT") or ""

                # 用户名
                user = getattr(req, "user", None)
                if user and getattr(user, "is_authenticated", False):
                    payload["username"] = getattr(user, "username", None)
                else:
                    payload["username"] = None

            # 入库
            SystemLog.objects.create(**payload)  # **解码字典
        except Exception:
            self.handleError(record)

    def _safe_message(self, record):
        """
        安全地获取日志消息文本，防止格式化错误
        """
        try:
            return record.getMessage()
        except Exception:
            return str(getattr(record, "msg", ""))[:1000]
